package viz.plugin.plugin_ocr

import android.app.Activity
import android.content.Intent
import android.graphics.BitmapFactory
import android.os.Build
import com.baidu.ai.edge.core.infer.InferConfig
import com.baidu.ai.edge.core.infer.InferManager
import com.baidu.ai.edge.core.util.FileUtil
import com.baidu.ai.edge.core.util.Util
import com.baidu.ai.edge.demo.CameraActivity
import com.baidu.ai.edge.ui.view.model.OcrResult
import com.google.gson.Gson
import com.viz.tools.Toast
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.PluginRegistry
import org.json.JSONException
import org.json.JSONObject
import java.io.FileInputStream
import java.io.IOException


/**
 * @title: OcrDelegate
 * @projectName plugin_ocr
 * @description:
 * @author zhangwei
 * @date 2020/9/29 14:36
 */
class OcrDelegate(
        private val activity: Activity,
        private var pendingResult: MethodChannel.Result? = null,
        private var methodCall: MethodCall? = null
) : PluginRegistry.ActivityResultListener {
    private var name = ""
    private var version = ""
    private var ak: String? = null
    private var sk: String? = null
    private var apiUrl: String? = null
    private var soc: String? = null
    private val socList = ArrayList<String>()
    private var type = 0

    // 请替换为您的序列号
    private val SERIAL_NUM: String? = null //null

    companion object {
        val REQUESTCODE_OCR = 20000
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
        when (requestCode) {
            REQUESTCODE_OCR -> {
                data?.apply {

                    val results: java.util.ArrayList<OcrResult?>? = data.getParcelableArrayListExtra("results")
                    results?.let {
                        val gson = Gson()
                        val ocrStr = gson.toJson(results)
                        pendingResult?.success(ocrStr)
                        clearMethodCallAndResult()
                    }
                }
            }
            20001 -> {
                pendingResult?.success("扫一扫")
                clearMethodCallAndResult()
            }
        }
        return true
    }

    fun jumpToCamera() {
        initConfig()

        if (checkChip()) {
            val intent = Intent(activity, CameraActivity::class.java)
            intent.putExtra("name", name)
            intent.putExtra("model_type", type)
            intent.putExtra("serial_num", SERIAL_NUM)

            if (apiUrl !== "null") {
                intent.putExtra("apiUrl", apiUrl)
                intent.putExtra("ak", ak)
                intent.putExtra("sk", sk)
            }

            intent.putExtra("soc", soc)
            activity.startActivityForResult(intent, REQUESTCODE_OCR)
        } else {
            Toast.show(activity, "socList:" + socList.toString() + ", Build.HARDWARE is :" + Build.HARDWARE)
        }

    }

    fun ocr(imagePath: String) {
        var manager:InferManager? = null
        try {
            val inputStream = FileInputStream(imagePath)
            val bitmap = BitmapFactory.decodeStream(inputStream, null, getBitmapOption(2)) //将图片的长和宽缩小味原来的1/2
            val config = InferConfig(activity.assets, "infer-ocr/config.json")
            config.setThread(Util.getInferCores())
            manager = InferManager(activity, config, null)
            val results = manager.ocr(bitmap, 0.3f)
            val ocrResults: MutableList<OcrResult> = java.util.ArrayList()
            for (i in results.indices) {
                val mOcrResultModel = results[i]
                mOcrResultModel?.apply {
                    ocrResults.add(OcrResult(i + 1, label, confidence, points))
                }
            }
            val gson = Gson()
            val ocrStr = gson.toJson(ocrResults)
            pendingResult?.success(ocrStr)
        } catch (e: Exception) {
            e.printStackTrace()
            pendingResult?.success("[]")
        } finally {
            manager?.destroy()
            clearMethodCallAndResult()
        }
    }

    private fun getBitmapOption(inSampleSize: Int): BitmapFactory.Options {
        val options = BitmapFactory.Options()
        options.inPurgeable = true
        options.inSampleSize = inSampleSize
        return options
    }

    private fun clearMethodCallAndResult() {
        methodCall = null
        pendingResult = null
    }

    private fun checkChip(): Boolean {
        if (socList.contains("dsp") && Build.HARDWARE.equals("qcom", ignoreCase = true)) {
            soc = "dsp"
            return true
        }
        if (socList.contains("npu") && (Build.HARDWARE.contains("kirin970") || Build.HARDWARE.contains("kirin980"))) {
            if (Build.HARDWARE.contains("kirin970")) {
                soc = "npu150"
            }
            if (Build.HARDWARE.contains("kirin980")) {
                soc = "npu200"
            }
            return true
        }
        if (socList.contains("npu-vinci") && (Build.HARDWARE.contains("kirin810")
                        || Build.HARDWARE.contains("kirin820") || Build.HARDWARE.contains("kirin990"))) {
            soc = "npu-vinci"
            return true
        }
        if (socList.contains("arm")) {
            soc = "arm"
            return true
        }
        if (socList.contains("xeye")) {
            soc = "xeye"
            return true
        }
        return false
    }

    /**
     * 读取json配置
     */
    private fun initConfig() {
        try {
            val configJson = FileUtil.readAssetFileUtf8String(activity.assets, "demo/config.json")
            val jsonObject = JSONObject(configJson)
            name = jsonObject.getString("model_name")
            version = jsonObject.getString("model_version")
            type = jsonObject.getInt("model_type")
            if (jsonObject.has("apiUrl")) {
                apiUrl = jsonObject.getString("apiUrl")
                ak = jsonObject.getString("ak")
                sk = jsonObject.getString("sk")
            }
            val jsonArray = jsonObject.getJSONArray("soc")
            for (i in 0 until jsonArray.length()) {
                val s = jsonArray.getString(i)
                socList.add(s)
            }
        } catch (e: IOException) {
            e.printStackTrace()
        } catch (e: JSONException) {
            e.printStackTrace()
        }
    }
}